﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Threading;

namespace FotoAlbum.Async
{
    class LoaderAsync : LoaderEvents
    {
        private const int MAXIMUM_WIDTH = 150;
        private const int MAXIMUM_HEIGHT = 150;

        public LoaderAsync()
        {
            ThreadPool.SetMaxThreads(4, 4);
        }

        /// <summary>
        /// Load an image asynchronously.
        /// </summary>
        public void LoadAsync(IEnumerable<FileInfo> fileInfos)
        {
            Counter.Abort();

            foreach (FileInfo fi in fileInfos)
            {
                int i = Counter.Start();
                var loadObj = new LoaderEventArgs(i, fi, null);
                ThreadPool.UnsafeQueueUserWorkItem(LoadImage, loadObj);
            }
        }

        /// <summary>
        /// Do the actual loading of images from the drive.
        /// </summary>
        /// <param name="obj">LoadObject containing information about the image.</param>
        private void LoadImage(object obj)
        {
            if (obj == null)
                throw new ArgumentNullException();
            var loadObj = (LoaderEventArgs)obj;
            
            // Abort when lower than the specified index.
            if (loadObj.Id <= Counter.AbortAt)
            {
                Counter.Completed();
                return;
            }
           
            try
            {
                using (Image image = Image.FromFile(loadObj.Path))
                {
                    // Ensure we use the actual image; not a premade thumbnail. (MSDN)
                    image.RotateFlip(RotateFlipType.Rotate180FlipNone);
                    image.RotateFlip(RotateFlipType.Rotate180FlipNone);

                    // Create the actual thumbnail.
                    Image temp = image.GetThumbnailImage(MAXIMUM_WIDTH, MAXIMUM_HEIGHT, null, IntPtr.Zero);

                    loadObj.Image = temp;

                    if (loadObj.Id <= Counter.AbortAt)
                    {
                        temp.Dispose();
                        return; // Goes to finally first!!
                    }
                    RaiseSingleImageLoadedEvent(loadObj);
                }
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(ex.GetType().ToString() + ": " + ex.Message);
            }
            finally
            {
                if (Counter.Completed())
                {
                    RaiseLoadingCompletedEvent();
                }
            }
        }
    }
}
